{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "97f23a5b",
   "metadata": {},
   "source": [
    "# 实验1：使用Python实现线性回归"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d37e5552",
   "metadata": {},
   "source": [
    "欢迎来到《线性回归》的第一个实验。\n",
    "\n",
    "我们将学习如何使用多元线性回归模型，基于多个特征变量预测目标变量的值。\n",
    "\n",
    "在本实验中，我们将根据两个输入特征预测对应的目标值。\n",
    "\n",
    "你可以通过单击代码区域，然后使用键盘快捷键 **Shift + Enter** 来运行代码。或者在选择代码后使用 **运行** 按钮执行代码。像这样的 MarkDown 文本可以通过双击编辑，并使用这些相同的快捷键保存。\n",
    "\n",
    "**文档中提供的代码具有顺序性，必须从前往后依次运行代码，不能跳跃执行，否则可能出现意想不到的错误！**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d0c0f48e",
   "metadata": {},
   "source": [
    "### 定义"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "722bd957",
   "metadata": {},
   "source": [
    "线性回归是一种用于预测连续因变量的模型，通过最小化预测值和实际值之间的误差，找到输入特征和输出之间的线性关系。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "25f390ae",
   "metadata": {},
   "source": [
    "### 公式"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "be438f30",
   "metadata": {},
   "source": [
    "$y=β_0+β_1x_1+β_2x_2+...+β_nx_n$\n",
    "\n",
    "其中，*y* 是目标变量，$x_1,x_2,...,x_n$ 是特征，$β_0$ 是截距，$β_n$ 是回归系数。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "47615310",
   "metadata": {},
   "source": [
    "### 第一步：导入所需的库"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f8fae04c",
   "metadata": {},
   "source": [
    "我们需要用到以下几个 Python 库：\n",
    "- `numpy`：用于处理数值计算和数组操作。\n",
    "- `sklearn.linear_model.LinearRegression`：提供线性回归模型。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "313a5242",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple\n",
      "Requirement already satisfied: scikit-learn in c:\\users\\neo\\anaconda3\\lib\\site-packages (1.2.2)\n",
      "Requirement already satisfied: numpy>=1.17.3 in c:\\users\\neo\\anaconda3\\lib\\site-packages (from scikit-learn) (1.26.2)\n",
      "Requirement already satisfied: scipy>=1.3.2 in c:\\users\\neo\\anaconda3\\lib\\site-packages (from scikit-learn) (1.11.4)\n",
      "Requirement already satisfied: joblib>=1.1.1 in c:\\users\\neo\\anaconda3\\lib\\site-packages (from scikit-learn) (1.2.0)\n",
      "Requirement already satisfied: threadpoolctl>=2.0.0 in c:\\users\\neo\\anaconda3\\lib\\site-packages (from scikit-learn) (2.2.0)\n"
     ]
    }
   ],
   "source": [
    "!pip install scikit-learn\n",
    "from sklearn.linear_model import LinearRegression\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a0212436",
   "metadata": {},
   "source": [
    "### 第二步：准备样本数据"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7d27f8c4",
   "metadata": {},
   "source": [
    "我们使用 NumPy 数组创建样本数据，其中：\n",
    "\n",
    "- 自变量 `X`：包含两个特征变量的二维数组。\n",
    "- 因变量 `y`：目标变量的一维数组。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ee97171b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 样本数据（X为输入特征，y为目标变量）\n",
    "X = np.array([[1, 2], [2, 3], [4, 5], [6, 7]])\n",
    "y = np.array([3, 5, 9, 13])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "649a8f41",
   "metadata": {},
   "source": [
    "这里的特征矩阵 X 包含 4 个样本，每个样本有 2 个特征。目标变量 y 是对应的 4 个值。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a6b9d9db",
   "metadata": {},
   "source": [
    "### 第三步：创建并训练线性回归模型"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9bc3a370",
   "metadata": {},
   "source": [
    "使用 `LinearRegression()` 创建模型,并通过 `fit()` 方法训练模型."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4c11c116",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建线性回归模型\n",
    "model = LinearRegression()\n",
    "model.fit(X, y)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e1c0a872",
   "metadata": {},
   "source": [
    "### 第四步：查看模型的训练结果"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a12cc483",
   "metadata": {},
   "source": [
    "训练完成后，我们可以查看模型的两个重要参数：\n",
    "\n",
    "- 截距（intercept）：模型方程中的常数项。\n",
    "- 系数（coefficients）：每个特征变量对应的权重，表示该特征对目标变量的影响程度。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2d6db078",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 输出模型参数：截距和系数\n",
    "print(f\"截距: {model.intercept_}\")\n",
    "print(f\"系数: {model.coef_}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a1b35b89",
   "metadata": {},
   "source": [
    "### 第五步：使用模型进行预测"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8415b40b",
   "metadata": {},
   "source": [
    "通过 `predict()` 方法，输入新的特征值来预测目标变量。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "29f080ed",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 预测\n",
    "y_pred = model.predict(np.array([[7, 8]]))\n",
    "print(f\"预测值: {y_pred}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3f3458f7",
   "metadata": {},
   "source": [
    "# 实验2：奶茶店销售额预测"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "74a641c6",
   "metadata": {},
   "source": [
    "在本实验中，我们将学习如何使用一元线性回归模型，预测奶茶店在不同气温下的销售额。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2f177fc0",
   "metadata": {},
   "source": [
    "### 第一步：导入所需的库"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "da63c58f",
   "metadata": {},
   "source": [
    "我们需要用到以下几个Python库：\n",
    "- `pandas`：用于读取和处理数据表格。\n",
    "- `matplotlib` 和 `seaborn`：用于绘图和可视化。\n",
    "- `sklearn.linear_model`：提供了常用的机器学习模型，这里使用其中的 `LinearRegression`。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "e7cf8ee4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple\n",
      "Requirement already satisfied: pandas in c:\\users\\neo\\anaconda3\\lib\\site-packages (2.1.4)\n",
      "Requirement already satisfied: seaborn in c:\\users\\neo\\anaconda3\\lib\\site-packages (0.12.2)\n",
      "Requirement already satisfied: numpy<2,>=1.23.2 in c:\\users\\neo\\anaconda3\\lib\\site-packages (from pandas) (1.26.2)\n",
      "Requirement already satisfied: python-dateutil>=2.8.2 in c:\\users\\neo\\anaconda3\\lib\\site-packages (from pandas) (2.8.2)\n",
      "Requirement already satisfied: pytz>=2020.1 in c:\\users\\neo\\anaconda3\\lib\\site-packages (from pandas) (2023.3.post1)\n",
      "Requirement already satisfied: tzdata>=2022.1 in c:\\users\\neo\\anaconda3\\lib\\site-packages (from pandas) (2023.3)\n",
      "Requirement already satisfied: matplotlib!=3.6.1,>=3.1 in c:\\users\\neo\\anaconda3\\lib\\site-packages (from seaborn) (3.8.0)\n",
      "Requirement already satisfied: contourpy>=1.0.1 in c:\\users\\neo\\anaconda3\\lib\\site-packages (from matplotlib!=3.6.1,>=3.1->seaborn) (1.2.0)\n",
      "Requirement already satisfied: cycler>=0.10 in c:\\users\\neo\\anaconda3\\lib\\site-packages (from matplotlib!=3.6.1,>=3.1->seaborn) (0.11.0)\n",
      "Requirement already satisfied: fonttools>=4.22.0 in c:\\users\\neo\\anaconda3\\lib\\site-packages (from matplotlib!=3.6.1,>=3.1->seaborn) (4.25.0)\n",
      "Requirement already satisfied: kiwisolver>=1.0.1 in c:\\users\\neo\\anaconda3\\lib\\site-packages (from matplotlib!=3.6.1,>=3.1->seaborn) (1.4.4)\n",
      "Requirement already satisfied: packaging>=20.0 in c:\\users\\neo\\anaconda3\\lib\\site-packages (from matplotlib!=3.6.1,>=3.1->seaborn) (23.1)\n",
      "Requirement already satisfied: pillow>=6.2.0 in c:\\users\\neo\\anaconda3\\lib\\site-packages (from matplotlib!=3.6.1,>=3.1->seaborn) (11.0.0)\n",
      "Requirement already satisfied: pyparsing>=2.3.1 in c:\\users\\neo\\anaconda3\\lib\\site-packages (from matplotlib!=3.6.1,>=3.1->seaborn) (3.0.9)\n",
      "Requirement already satisfied: six>=1.5 in c:\\users\\neo\\anaconda3\\lib\\site-packages (from python-dateutil>=2.8.2->pandas) (1.16.0)\n"
     ]
    }
   ],
   "source": [
    "!pip install pandas seaborn\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "from sklearn.linear_model import LinearRegression"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4f177500",
   "metadata": {},
   "source": [
    "### 第二步：读取奶茶店销售数据"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9488d0e3",
   "metadata": {},
   "source": [
    "我们将使用一份 CSV 文件格式的数据，其中包含了每日的最高气温与对应的销售额。\n",
    "\n",
    "让我们使用 `pandas` 读取该数据文件，并展示前几行内容，确认数据结构。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "52fe7a9e",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "file_path = 'data/一元奶茶店销售数据.csv'\n",
    "uploaded_data = pd.read_csv(file_path, encoding='gbk')\n",
    "uploaded_data.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a1b23853",
   "metadata": {},
   "source": [
    "### 第三步：准备模型训练所需的数据"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "57c02c1f",
   "metadata": {},
   "source": [
    "为了建立模型，我们需要从数据中提取：\n",
    "- 自变量 X：也叫特征变量，这里是“当日最高气温(℃)”\n",
    "- 因变量 y：我们希望预测的目标变量，这里是“销售额(元)”"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6d62f7c5",
   "metadata": {},
   "outputs": [],
   "source": [
    "X = uploaded_data[['当日最高气温(℃)']]\n",
    "y = uploaded_data['销售额(元)']"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e5783f4e",
   "metadata": {},
   "source": [
    "### 第四步：创建并训练线性回归模型"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9d1a57f0",
   "metadata": {},
   "source": [
    "现在我们使用 `LinearRegression()` 来建立模型，并使用我们提取的 `X` 和 `y` 数据进行训练。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "72b506d8",
   "metadata": {},
   "outputs": [],
   "source": [
    "model = LinearRegression()\n",
    "model.fit(X, y)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9126bfec",
   "metadata": {},
   "source": [
    "### 第五步：查看模型的训练结果"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b9a09ea4",
   "metadata": {},
   "source": [
    "训练完成后，我们可以查看模型的两个重要参数：\n",
    "- 截距（intercept）：表示当气温为0℃时的预测销售额。\n",
    "- 斜率（slope）：表示气温每升高1℃，销售额的平均增长量。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e42c492f",
   "metadata": {},
   "outputs": [],
   "source": [
    "intercept = model.intercept_\n",
    "slope = model.coef_[0]\n",
    "print(f\"截距: {intercept:.2f}, 斜率: {slope:.2f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9d14c870",
   "metadata": {},
   "source": [
    "### 第六步：绘制散点图与回归线"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d03bf133",
   "metadata": {},
   "source": [
    "我们将使用 `seaborn` 库的 `regplot()` 函数来绘制数据点和拟合的回归直线。\n",
    "通过可视化，我们可以更直观地看到气温与销售额之间的关系。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "716f8907",
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure(figsize=(8, 6))\n",
    "sns.regplot(\n",
    "    x='当日最高气温(℃)',\n",
    "    y='销售额(元)',\n",
    "    data=uploaded_data,\n",
    "    ci=None,\n",
    "    line_kws={\"color\": \"red\", \"label\": f\"y = {intercept:.2f} + {slope:.2f}x\"}\n",
    ")\n",
    "plt.title('Temperature vs Sales Regression', fontsize=16)\n",
    "plt.xlabel('Max Temperature (℃)', fontsize=12)\n",
    "plt.ylabel('Sales (Yuan)', fontsize=12)\n",
    "plt.legend()\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9b47f9df",
   "metadata": {},
   "source": [
    "### 🤔 思考与讨论"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "84324aff",
   "metadata": {},
   "source": [
    "**Q1：你认为随着气温上升，奶茶店的销售额是否会一定增加？图中体现了什么样的趋势？**\n",
    "\n",
    "**Q2：除了气温，还有哪些因素可能会影响奶茶店的销量？如何将它们也加入模型？**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5174532d",
   "metadata": {},
   "source": [
    "# 作业：定价与销量预测"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "19185eb7",
   "metadata": {},
   "source": [
    "在本实验中，我们继续使用一元线性回归，探索“价格”与“销量”之间的关系。\n",
    "通过分析定价策略对销量的影响，帮助优化商业决策。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7847999c",
   "metadata": {},
   "source": [
    "### 第一步：导入所需的库"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b964c516",
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.linear_model import LinearRegression\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "43864bd7",
   "metadata": {},
   "source": [
    "### 第二步：读取数据"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e2b4eb6f",
   "metadata": {},
   "source": [
    "我们将读取 `pricing_data.csv` 文件，其中包含不同价格下的奶茶销售量数据。\n",
    "先读取并查看前几行数据："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6221e8eb",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "6437aa10",
   "metadata": {},
   "source": [
    "### 第三步：准备特征与目标变量"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "44ce92ef",
   "metadata": {},
   "source": [
    "选择价格作为自变量 `X`，销售额作为因变量 `y`。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "06e78ba8",
   "metadata": {},
   "outputs": [],
   "source": [
    "X = uploaded_data[['Price']]\n",
    "y = uploaded_data['Sales']"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "78e3c542",
   "metadata": {},
   "source": [
    "### 第四步：训练线性回归模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "710cf509",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "f648aaee",
   "metadata": {},
   "source": [
    "### 第五步：查看模型参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "66b05aef",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "ac741e74",
   "metadata": {},
   "source": [
    "### 第六步：绘制回归图"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7b509cae",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "b7f37293",
   "metadata": {},
   "source": [
    "### 🤔 思考与讨论"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fc56995e",
   "metadata": {},
   "source": [
    "**Q1：模型的斜率为负值意味着什么？你如何理解价格和销售额之间的关系？**\n",
    "\n",
    "**Q2：是否所有商品的价格与销量都存在线性关系？若关系更复杂应如何处理？**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d4600821",
   "metadata": {},
   "source": [
    "# 实验4：使用Python实现二元线性回归"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0e1b4f27",
   "metadata": {},
   "source": [
    "当一个特征变量不足以预测目标值时，可以引入多个特征。\n",
    "本实验中，我们将使用两个变量来预测销量，构建一个二元线性回归模型。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aba44780",
   "metadata": {},
   "source": [
    "### 第一步：导入库与准备数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "978db2cb",
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.linear_model import LinearRegression\n",
    "import numpy as np\n",
    "\n",
    "# 构造两个自变量（特征）和一个因变量（目标）\n",
    "X = np.array([[1, 3], [2, 4], [3, 5], [6, 8], [7, 9]])\n",
    "y = np.array([[10], [12.687], [17.35], [21.8], [27]])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5742858e",
   "metadata": {},
   "source": [
    "如果你想继续添加自变量因变量关系，代码需要进行怎样的改动？"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6303e712",
   "metadata": {},
   "source": [
    "### 第二步：建立并训练模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "9be9e64c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>#sk-container-id-1 {color: black;background-color: white;}#sk-container-id-1 pre{padding: 0;}#sk-container-id-1 div.sk-toggleable {background-color: white;}#sk-container-id-1 label.sk-toggleable__label {cursor: pointer;display: block;width: 100%;margin-bottom: 0;padding: 0.3em;box-sizing: border-box;text-align: center;}#sk-container-id-1 label.sk-toggleable__label-arrow:before {content: \"▸\";float: left;margin-right: 0.25em;color: #696969;}#sk-container-id-1 label.sk-toggleable__label-arrow:hover:before {color: black;}#sk-container-id-1 div.sk-estimator:hover label.sk-toggleable__label-arrow:before {color: black;}#sk-container-id-1 div.sk-toggleable__content {max-height: 0;max-width: 0;overflow: hidden;text-align: left;background-color: #f0f8ff;}#sk-container-id-1 div.sk-toggleable__content pre {margin: 0.2em;color: black;border-radius: 0.25em;background-color: #f0f8ff;}#sk-container-id-1 input.sk-toggleable__control:checked~div.sk-toggleable__content {max-height: 200px;max-width: 100%;overflow: auto;}#sk-container-id-1 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {content: \"▾\";}#sk-container-id-1 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-1 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-1 input.sk-hidden--visually {border: 0;clip: rect(1px 1px 1px 1px);clip: rect(1px, 1px, 1px, 1px);height: 1px;margin: -1px;overflow: hidden;padding: 0;position: absolute;width: 1px;}#sk-container-id-1 div.sk-estimator {font-family: monospace;background-color: #f0f8ff;border: 1px dotted black;border-radius: 0.25em;box-sizing: border-box;margin-bottom: 0.5em;}#sk-container-id-1 div.sk-estimator:hover {background-color: #d4ebff;}#sk-container-id-1 div.sk-parallel-item::after {content: \"\";width: 100%;border-bottom: 1px solid gray;flex-grow: 1;}#sk-container-id-1 div.sk-label:hover label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-1 div.sk-serial::before {content: \"\";position: absolute;border-left: 1px solid gray;box-sizing: border-box;top: 0;bottom: 0;left: 50%;z-index: 0;}#sk-container-id-1 div.sk-serial {display: flex;flex-direction: column;align-items: center;background-color: white;padding-right: 0.2em;padding-left: 0.2em;position: relative;}#sk-container-id-1 div.sk-item {position: relative;z-index: 1;}#sk-container-id-1 div.sk-parallel {display: flex;align-items: stretch;justify-content: center;background-color: white;position: relative;}#sk-container-id-1 div.sk-item::before, #sk-container-id-1 div.sk-parallel-item::before {content: \"\";position: absolute;border-left: 1px solid gray;box-sizing: border-box;top: 0;bottom: 0;left: 50%;z-index: -1;}#sk-container-id-1 div.sk-parallel-item {display: flex;flex-direction: column;z-index: 1;position: relative;background-color: white;}#sk-container-id-1 div.sk-parallel-item:first-child::after {align-self: flex-end;width: 50%;}#sk-container-id-1 div.sk-parallel-item:last-child::after {align-self: flex-start;width: 50%;}#sk-container-id-1 div.sk-parallel-item:only-child::after {width: 0;}#sk-container-id-1 div.sk-dashed-wrapped {border: 1px dashed gray;margin: 0 0.4em 0.5em 0.4em;box-sizing: border-box;padding-bottom: 0.4em;background-color: white;}#sk-container-id-1 div.sk-label label {font-family: monospace;font-weight: bold;display: inline-block;line-height: 1.2em;}#sk-container-id-1 div.sk-label-container {text-align: center;}#sk-container-id-1 div.sk-container {/* jupyter's `normalize.less` sets `[hidden] { display: none; }` but bootstrap.min.css set `[hidden] { display: none !important; }` so we also need the `!important` here to be able to override the default hidden behavior on the sphinx rendered scikit-learn.org. See: https://github.com/scikit-learn/scikit-learn/issues/21755 */display: inline-block !important;position: relative;}#sk-container-id-1 div.sk-text-repr-fallback {display: none;}</style><div id=\"sk-container-id-1\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>LinearRegression()</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item\"><div class=\"sk-estimator sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-1\" type=\"checkbox\" checked><label for=\"sk-estimator-id-1\" class=\"sk-toggleable__label sk-toggleable__label-arrow\">LinearRegression</label><div class=\"sk-toggleable__content\"><pre>LinearRegression()</pre></div></div></div></div></div>"
      ],
      "text/plain": [
       "LinearRegression()"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "reg = LinearRegression()\n",
    "reg.fit(X, y)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7fb7af51",
   "metadata": {},
   "source": [
    "### 第三步：输出模型参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "2a1d2a21",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Coefficients (斜率): [[1.29931716 1.29931716]]\n",
      "Intercept (截距): [5.29395522]\n",
      "y = 1.30 * x1 + 1.30 * x2 + 5.29\n"
     ]
    }
   ],
   "source": [
    "print(\"Coefficients (斜率):\", reg.coef_)\n",
    "print(\"Intercept (截距):\", reg.intercept_)\n",
    "print(\"y = {:.2f} * x1 + {:.2f} * x2 + {:.2f}\".format(\n",
    "    reg.coef_[0][0], reg.coef_[0][1], reg.intercept_[0]))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f5020a91",
   "metadata": {},
   "source": [
    "### 🤔 思考与讨论"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4752b2db",
   "metadata": {},
   "source": [
    "**Q1：如果只使用一个变量（如x1或x2）建立模型，预测效果会怎样？**\n",
    "\n",
    "**Q2：你能举出一个现实生活中二元线性回归可以应用的例子吗？**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "652a6751",
   "metadata": {},
   "source": [
    "# 实验5：使用Python实现非线性回归（多项式回归）"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a945a2c3",
   "metadata": {},
   "source": [
    "在前面的实验中，我们使用了线性回归来拟合变量之间的关系，适用于数据趋势是“直线”时。\n",
    "\n",
    "但在现实中，很多现象并不是简单的线性关系，例如物理中的加速度变化、价格与销量的非线性波动等。\n",
    "\n",
    "**本实验将介绍如何用多项式回归来拟合这些非线性关系。**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c2d7f80b",
   "metadata": {},
   "source": [
    "### 第一步：生成模拟的非线性数据"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1ac5aa1f",
   "metadata": {},
   "source": [
    "我们使用 numpy 生成一个包含噪声的二次函数形式的数据集，形式大致为：\n",
    "\n",
    "`y = 2 + x + 0.5 * x² + 噪声`\n",
    "\n",
    "这代表一个抛物线趋势，但由于加入了噪声，更接近真实数据分布。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0d37b956",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn.preprocessing import PolynomialFeatures\n",
    "from sklearn.linear_model import LinearRegression\n",
    "from sklearn.metrics import mean_squared_error\n",
    "\n",
    "# 构造非线性数据\n",
    "np.random.seed(0)\n",
    "x = np.linspace(-3, 3, 100)\n",
    "y = 2 + x + 0.5 * x**2 + np.random.normal(0, 1, 100)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0f8fd195",
   "metadata": {},
   "source": [
    "### 第二步：构造多项式特征"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f3980011",
   "metadata": {},
   "source": [
    "线性回归只能处理一阶直线关系，我们需要将自变量 `x` 转换为多项式特征。\n",
    "\n",
    "通过 `PolynomialFeatures(degree=2)`，我们能扩展出 [1, x, x²] 三个特征。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "94d53898",
   "metadata": {},
   "outputs": [],
   "source": [
    "poly = PolynomialFeatures(degree=2)\n",
    "x_poly = poly.fit_transform(x.reshape(-1, 1))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "147d5e7e",
   "metadata": {},
   "source": [
    "### 第三步：训练多项式回归模型"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cd89ce6c",
   "metadata": {},
   "source": [
    "使用转换后的 `x_poly` 数据训练回归模型，并进行预测。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ee9b8d60",
   "metadata": {},
   "outputs": [],
   "source": [
    "model = LinearRegression()\n",
    "model.fit(x_poly, y)\n",
    "y_pred = model.predict(x_poly)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "86e82996",
   "metadata": {},
   "source": [
    "### 第四步：评估模型"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "84a04bf6",
   "metadata": {},
   "source": [
    "我们使用均方误差 (MSE) 来评估模型拟合效果，并查看训练出的系数和截距。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "26aa01fc",
   "metadata": {},
   "outputs": [],
   "source": [
    "mse = mean_squared_error(y, y_pred)\n",
    "print(f\"多项式回归 MSE: {mse:.4f}\")\n",
    "print(f\"系数: {model.coef_}, 截距: {model.intercept_}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fbbe399b",
   "metadata": {},
   "source": [
    "### 第五步：绘制拟合图"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4df00331",
   "metadata": {},
   "source": [
    "我们将原始散点图与回归拟合曲线一起绘制，以观察模型是否成功捕捉到了非线性趋势。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ae1bf332",
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.rcParams['font.sans-serif'] = [\"SimHei\"]\n",
    "plt.rcParams['axes.unicode_minus'] = False\n",
    "plt.scatter(x, y, c='b', label='实际数据')\n",
    "plt.plot(x, y_pred, 'r', label='多项式回归')\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d53b3042",
   "metadata": {},
   "source": [
    "### 🤔 思考与讨论"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9a322295",
   "metadata": {},
   "source": [
    "**Q1：观察拟合图像，你认为模型是否较好地捕捉到了非线性趋势？为什么？**\n",
    "\n",
    "**Q2：如果我们提高多项式阶数为5或10，会发生什么？如何判断是否过拟合？**\n",
    "\n",
    "**Q3：非线性回归在哪些实际场景中有优势？能举出几个例子吗？**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4c8d575c",
   "metadata": {},
   "source": [
    "## 📝 实验总结"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d2e6a4a2",
   "metadata": {},
   "source": [
    "通过本次线性与非线性回归实验的学习，我们掌握了：\n",
    "- **一元线性回归模型**的建立方法及可视化\n",
    "- 多个变量参与的**二元线性回归**建模技巧\n",
    "- 如何利用**多项式特征**进行**非线性**拟合\n",
    "\n",
    "这些回归模型广泛应用于商业预测、科学分析、工程建模等领域，是机器学习的重要基础。\n",
    "\n",
    "**建议你在后续学习中尝试：**\n",
    "- 利用真实数据进行模型建模与验证\n",
    "- 使用评估指标（如MSE、R²）判断模型好坏\n",
    "- 学习正则化技术避免过拟合\n",
    "\n",
    "继续努力，逐步掌握更强大的数据分析与建模能力！"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
